# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import json
import re
import requests

from django.core.handlers.wsgi import WSGIRequest
from django.http import JsonResponse
from django.shortcuts import render
from django.conf import settings

from list_of_people import list_of_people
from . import tasks


class PeopleService:
    """ Логика для работы с людьми """

    @staticmethod
    def get_list_of_field_names():
        """ Получаем список названий полей в указанном порядке """

        information_about_people = (
            'id',
            'name',
            'surname',
            'patronymic',
            'date_of_birth',
            'email',
            'login',
            'password'
        )
        return information_about_people


    @staticmethod
    def get_number_of_people_from_database():
        """ Получаем количество человек из бд """
        return len(list_of_people)


    @staticmethod
    def get_field_value_of_all_people(field):
        # type (str) -> list
        """ Получаем значение выбранного поля всех людей """

        values = [people[field] for people in list_of_people.values()]
        return values

    
    def get_necessary_information(self, request):
        # type (object, WSGIRequest) -> JsonResponse
        """ Получаем необходимую информацию """

        def get_list_of_all_people():
            """ Получаем список всех людей """
            return list_of_people


        # ВЫШЕ ОПРЕДЕЛЕНИЕ ФУНКЦИЙ

        if request.GET.get('get_list_of_all_people'):
            result = get_list_of_all_people()
            return JsonResponse(result)


    def perform_necessary_action(self):
        # type (object, WSGIRequest) -> JsonResponse
        """ Выполняем необходиме действие """
        pass


class UnisenderCreatingURLService:

    def get_initial_url_for_request(self, method, lang='en', **kwargs):
        # type: (object, str, str, dict) -> str
        """ Получаем начальный url для обращения к API """

        # 'https://api.unisender.com/LANG/api/METHOD?format=json&api_key=KEY&arg1=ARG_1&argN=ARG_N'
        API_KEY = settings.UNISENDER_API_KEY
        initial_url = 'https://api.unisender.com/%s/api/%s?format=json&api_key=%s&' \
            % (lang, method, API_KEY)

        for key in kwargs:
            initial_url += '%s=%s&' % (key, kwargs[key])

        initial_url = re.sub('&$', '', initial_url).encode()
        return initial_url


    def get_url_to_create_malling_list(self, title):
        # type: (object, str) -> str
        """ Получаем url для создания какого-то списка рассылок """

        url = self.get_initial_url_for_request(
            method='createList',
            title=title
        )
        return url


    def get_url_to_select_all_malling_lists(self):
        # type: (object) -> str
        """ Получаем url для выборки всех списков рассылки """

        url = self.get_initial_url_for_request(
            method='getLists'
        )
        return url


    def get_url_to_add_people_to_malling_list(self, malling_list_id, email):
        # type: (object, int, str) -> str
        """ Получаем url для добавления человека в список рассылок """

        url = self.get_initial_url_for_request(
            method='subscribe'
        )
        url = '%s&list_ids=%s&fields[email]=%s&double_optin=3' % \
            (url, malling_list_id, email)
        url = url.encode('utf-8')

        return url


    def get_url_to_check_people_presence_in_malling_list(
        self, email, malling_list_id):
        # type (object)
        """
        Получаем url для проверки присутствия пользователя в
        каком-то списке рассылок
        """

        url = self.get_initial_url_for_request(
            method='isContactInLists'
        )

        url = '%s&email=%s&list_ids=%s&condition=and' % \
            (url, email, malling_list_id)

        return url


    def get_url_to_create_message(self, data):
        """ Получаем url для создания сообщения """

        url = self.get_initial_url_for_request(
            method='createEmailMessage',
        )
        url = '%s&sender_name=%s&sender_email=%s&list_id=%d&template_id=%d' % \
            (url, data['sender_name'], data['sender_email'], data['list_id'], data['template_id'])
        return url


    def get_url_to_create_custom_field(self, title, type):
        # type (str, str) -> str
        """ Получаем url для создания пользовательского поля """

        url = self.get_initial_url_for_request(
            method='createField',
        )
        url = '%s&name=%s&type=%s' % (url, title, type)

        return url


    def get_url_to_create_email_template(self, data):
        # type (object, dict) -> str
        """ Получаем url для создания шаблона email """

        url = self.get_initial_url_for_request(
            method='createEmailTemplate',
        )
        url = '%s&title=%s&subject=%s&body=%s' % \
            (url, data['title'], data['subject'], data['body'])

        return url


    def get_url_to_select_all_email_templates(self):
        # type (object) -> str
        """ Получаем url для выборки всех шаблонов сообщений """

        url = self.get_initial_url_for_request(
            method='getTemplates',
        )
        return url


    def get_url_to_create_malling_list_template(self, data):
        # type: (object) -> str
        """ Получаем url для создания шаблона списка рассылок """

        url = self.get_initial_url_for_request(
            method='updateOptInEmail',
        )
        url = '%s&sender_name=%s&sender_email=%s&subject=%s&body=%s&list_id=%s' % \
            (url, data['sender_name'], data['sender_email'],
             data['subject'], data['body'], data['malling_list_id'])

        return url


class UnisenderService(UnisenderCreatingURLService):
    """ Логика для работы с API сервиса UNISENDER """

    def __init__(self):
        self.people_object = PeopleService()


    def import_contacts_to_service(self):
        # type: (object) -> None
        """ Импортируем контакты в сервис (Unisender) """

        def add_parameters_for_request(url, list_of_field_names):
            # type: (str, list) -> str
            """ Получаем параметры для запроса """

            for count, parameter in enumerate(list_of_field_names, 0):
                text = '&field_names[%d]=%s' % (count, parameter)
                url += text

            return url

        def add_values_by_parameters(url, list_of_field_names):
            # type: (str, list) -> str
            """ Добавляем значения по параметрам """

            number_of_people_from_database = self.people_object.get_number_of_people_from_database()

            for number in range(number_of_people_from_database):
                for field in list_of_field_names:
                    index = list_of_field_names.index(field)
                    value = list_of_people[number][field]
                    more_text = '&data[%d][%d]=%s' % (number, index, value)
                    url += more_text

            return url


        # ВЫШЕ ОПРЕДЕЛЕНИЕ ФУНКЦИЙ

        list_of_field_names = self.people_object.get_list_of_field_names()
        url = self.get_initial_url_for_request(
            method='importContacts',
        )
        url = add_parameters_for_request(url, list_of_field_names)
        url = add_values_by_parameters(url, list_of_field_names)
        url = url.encode('utf-8')
        requests.post(url)


    def check_existence_of_malling_list(self, title):
        # type: (object, str) -> bool
        """ Проверяем, есть ли список рассылок с указанным названием """

        malling_list_id = self.get_malling_list(title)
        if malling_list_id: return True
        elif malling_list_id: return False


    def create_malling_list(self, title='standard_malling_list', full_response=False):
        # type: (object, str, bool) -> dict
        """ Создаем список рассылок """

        url = self.get_url_to_create_malling_list(title)
        response = requests.post(url)
        result = response.json()

        if self.check_existence_of_malling_list(title): return
        if not full_response: result = result['result']

        return result


    def check_people_presence_in_malling_list(
        self, email, malling_list_id, full_response=False):
        # type (object, str, int) -> None
        """ Проверяем присутствие человека в списке рассылок """

        url = self.get_url_to_check_people_presence_in_malling_list(
            email, malling_list_id
        )
        response = requests.post(url)
        result = response.json()

        if not full_response: result = result['result']

        return result


    def get_all_malling_lists(self, full_response=False):
        # type(object) -> None
        """ Получаем список всех имеющихся рассылок """

        url = self.get_url_to_select_all_malling_lists()
        response = requests.post(url)
        result = response.json()

        if not full_response: result = result['result']

        return result


    def get_malling_list(self, title='standard_malling_list', only_element='id'):
        # type: (object, str, str) -> int or dict
        """ Получаем список рассылок """

        malling_list = filter(
            lambda element: element['title'] == title,
            self.get_all_malling_lists()
        )
        if not malling_list: raise ValueError('Список рассылок не найден')
        if only_element: return malling_list[0][only_element]
        return malling_list


    def create_message_without_sending(self, only_message_id=True, full_response=False):
        """ Создаем сообщение без отправки """

        malling_list_id = self.get_malling_list()
        template_id_for_email = self.get_standard_template_for_email()

        _data = {
            'sender_name': 'Sasuke Uchiha',
            'sender_email': 'ilya.gordeev.2022@mail.ru',
            'template_id': template_id_for_email,
            'list_id': malling_list_id
        }

        url = self.get_url_to_create_message(_data)
        response = requests.post(url)
        result = response.json()

        if not full_response: result = result['result']
        if only_message_id: result = result['message_id']

        return result


    def add_people_to_malling_list(self, malling_list_id, list_of_email):
        # type: (object, int, list) -> None
        """ Добавляем людей в список рассылок """

        list_of_people_to_add_to_malling_group_url = set()

        for email in list_of_email:
            url = self.get_url_to_add_people_to_malling_list(
                malling_list_id,
                email
            )
            is_present_in_group = self.check_people_presence_in_malling_list(
                email, malling_list_id
            )
            if not is_present_in_group:
                list_of_people_to_add_to_malling_group_url.add(url)

        list_of_people_to_add_to_malling_group_url = list(
            list_of_people_to_add_to_malling_group_url
        )
        tasks.add_people_to_malling_list_task.delay(
            list_of_people_to_add_to_malling_group_url
        )


    def add_all_people_to_malling_list(self):
        # type: (object) -> None
        """
        Добавляем всех (которые не добавлены) людей в список для рассылки
        """

        malling_list_id = self.get_malling_list()
        list_of_email = self.people_object.get_field_value_of_all_people(
            'email'
        )
        self.add_people_to_malling_list(malling_list_id, list_of_email)


    def create_custom_field(self):
        # type: (object) -> None
        """ Создаем пользовательские поля для шаблонов сообщений """

        list_of_urls_for_creating_fields = []
        _required_user_field = {
            0: {'title': 'id', 'type': 'number'},
            1: {'title': 'name', 'type': 'string'},
            2: {'title': 'surname', 'type': 'string'},
            3: {'title': 'patronymic', 'type': 'string'},
            4: {'title': 'date_of_birth', 'type': 'date'},
            5: {'title': 'email', 'type': 'string'},
            6: {'title': 'login', 'type': 'string'},
            7: {'title': 'password', 'type': 'string'},
        }

        for field in _required_user_field.values():
            url = self.get_url_to_create_custom_field(
                title=field['title'],
                type=field['type']
            )
            list_of_urls_for_creating_fields.append(url)

        tasks.create_custom_fields_task.delay(
            list_of_urls_for_creating_fields
        )


    def create_standard_template_for_email(self):
        # type: (object) -> None
        """ Создаем стандартный шаблон для сообщения """

        _standard_template_data = {
            'title': 'standard_template',
            'subject': 'Приветствую тебя, {{surname}} {{name}}',
            'body': 'Сообщаю, что Вы родились - {{date_of_birth}}'
        }
        url = self.get_url_to_create_email_template(_standard_template_data)
        response = requests.post(url)


    def get_all_templates_for_email(self, full_response=False):
        # type (object, bool) -> None
        """ Получаем все шаблоны для сообщения """

        url = self.get_url_to_select_all_email_templates()
        response = requests.post(url)
        result = response.json()

        if not full_response: result = result['result']

        return result


    def get_standard_template_for_email(
        self, title='standard_template', only_template_id=True):
        # type: (object, str, bool) -> None
        """ Получаем шаблон для email """

        all_templates = self.get_all_templates_for_email()
        template = filter(
            lambda template: template['title'] == title,
            all_templates
        )
        if only_template_id: return template[0]['id']
        return template


    def create_template_for_malling_list(self, malling_list_id=False):
        # type: (object, int) -> None
        """ Создаем шаблон для списка рассылок """

        malling_list_id = malling_list_id if malling_list_id else self.get_malling_list() 
        _malling_list_template_data = {
            'sender_name': 'Sasuke Uchiha',
            'sender_email': 'anton_klimeshov@rambler.ru',
            'subject': 'Подтвердите адрес Вашей электронной почты',
            'body': 'Здравствуйте {{name}}! Нажмите <a href="{{ConfirmUrl}}">сюда</a> чтобы подтвердить Ваш адрес.',
            'malling_list_id': malling_list_id
        }
        url = self.get_url_to_create_malling_list_template(_malling_list_template_data)
        response = requests.post(url)


    def perform_initial_actions_for_unisender(self):
        """ Выполняем начальные действия с сервисом Unisinder """

        self.create_standard_template_for_email()
        self.create_malling_list()
        self.create_template_for_malling_list()
        self.create_custom_field()
        self.import_contacts_to_service()
        self.create_message_without_sending()
        self.add_all_people_to_malling_list()


class MessageService:
    """ Логика для работы с отправкой сообщений """
    
    def get_necessary_information(self, request):
        # type: (object, WSGIRequest) -> JsonResponse
        """ Получаем необходимую информацию """

        def get_list_of_all_messages(request):
            # type: (WSGIRequest) -> None

            initial_list = request.session.get('list_of_all_messages', False)


        # ВЫШЕ ОПРЕДЕЛЕНИЕ ФУНКЦИЙ

        if request.GET.get('get_list_of_all_messages'):
            get_list_of_all_messages(request)
            return JsonResponse({'status': 200})


    def perform_necessary_action(self, request):
        # type (object, WSGIRequest) -> JsonResponse
        """ Выполняем необходиме действие """


        def work_on_sending_message(request):
            # type: (WSGIRequest) -> JsonResponse
            """ Работаем над отправкой сообщений """
            pass


        # ВЫШЕ ОПРЕДЕЛЕНИЕ ФУНКЦИЙ

        if request.POST.get('sendMessage'):
            work_on_sending_message(request)
            return JsonResponse({'status': 200})


class DisplayingMessagesService:

    def get_necessary_information(self, request):
        # type: (object, WSGIRequest) -> JsonResponse
        """ Получаем необходимую информацию """

        def get_list_of_all_messages(request):
            # type: (WSGIRequest) -> None
            """ Получаем список всех сообщений """

            initial_list = request.session.get('list_of_all_messages', False)
            initial_list = initial_list if initial_list else {}
            return JsonResponse(initial_list)


        def mark_message_as_read(request):
            """ Помечаем сообщение прочитанным """
            # type: (WSGIRequest) -> None
            pass


        # ВЫШЕ ОПРЕДЕЛЕНИЕ ФУНКЦИЙ

        if request.GET.get('get_list_of_all_messages'):
            return get_list_of_all_messages(request)
        elif request.GET.get('mark_message_as_read'):
            return mark_message_as_read(request)
        else:
            return render(request, 'mail/displaying_messages.html')
